import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/pages/third/bloc_page.dart';

import '../../../widgets/app_widgets.dart';

class StatefulWidgetPage extends PageWithTitle {
  const StatefulWidgetPage() : super("状态组件(StatefulWidget)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    var times = 0;
    var isOpen = false;
    return [
      const PrimaryTitle("简介"),
      const BodyText("页面基本都有用户交互而非静态展示，在需要根据状态更新页面时，使用StatefulWidget来实现"),
      const LabelText("建议使用第三方库Bloc来实现状态管理与界面更新,他封装得好，可以局部小组"
          "件订阅所需状态进行更新，而不是整个状态组件重建"),
      const LabelText("- BlocListener，监听状态变化，执行任务"),
      const LabelText("- BlocBuilder，监听状态变化，根据新状态重新构建ui"),
      const PageLink(BlocPage()),
      AppSpacer.large,
      const _Example(),
      const UlItem("StatefulWidget"),
      AppSpacer.large,
      const OlItem(1, "createState"),
      const BodyText("创建状态对象，该状态将存储在element中，实现widget更新后状态还可以延续"),
      AppSpacer.large,
      const UlItem("State"),
      const BodyText(
          "状态对象，泛型一般就是当前的Widget类型，state中包含widget，若构建组件时需要从widget取参就可以不进行强转了。"),
      const OlItem(1, "build"),
      const BodyText("构建组件，因为需要根据当前状态构建组件，所以build方法在state中实现。"),
      const OlItem(2, "setState"),
      const BodyText(
          "设置新状态，它的参数是一个回调接口，函数内部先标记element需要rebuild，然后执行回调接口，我们在回调中更新状态，等到下次build触发时根据新状态构建ui即可"),
      AppSpacer.large,
      StatefulBuilder(builder: (context, setState) {
        return Row(
          children: [
            //根据当前的切换次数和开关状态构建ui
            Text("switch times:$times"),
            Switch(
              value: isOpen,
              //监听开关状态变化，通过setState标记需要重新build，然后更新状态值
              onChanged: (v) => setState(() {
                times++;
                isOpen = v;
              }),
            )
          ],
        );
      }),
      const OlItem(1, "StatefulBuilder"),
      const BodyText("StatefulWidget的回调版本"),
      const LabelText("- 好处，使开发者不需要重复地创建Widget和State类，他直接将组件构建和"
          "状态更新通过回调方式暴露出来"),
      const LabelText("- 坏处，状态存储也转移到外部组件，这东西始终不是订阅状态变量自动更新，"
          "抽出来地状态即使被别的组件修改也无法通知到所有组件，他只是修改状态更新自身，所以这个"
          "也挺鸡肋，还破坏了面向对象地封装特性"),
      const NoticeText("我更建议在需要局部更新组件状态时使用状态组件封装实现，在需要与其它组"
          "件共享状态和订阅更新时建议使用Bloc来实现"),
    ];
  }
}

class _Example extends StatefulWidget {
  const _Example();

  @override
  State<StatefulWidget> createState() {
    return _ExampleState();
  }
}

class _ExampleState extends State<_Example> {
  var times = 0;
  var isOpen = false;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        //根据当前的切换次数和开关状态构建ui
        Text("switch times:$times"),
        Switch(
          value: isOpen,
          //监听开关状态变化，通过setState标记需要重新build，然后更新状态值
          onChanged: (v) => setState(() {
            times++;
            isOpen = v;
          }),
        )
      ],
    );
  }
}
